#define _CRT_SECURE_NO_WARNINGS 1
#include "string.h"

namespace xsc
{
	const size_t string::npos = -1;
	void string::resize(size_t n, char ch)
	{
		if (n <= _size)
		{
			_size = n;
		}
		else
		{
			char* s = new char[n + 1];
			memset(s, ch, n + 1);
			strcpy(s, _str);
			delete[] _str;

			_size = n;
			_capacity = n;
			_str = s;
		}
	}

	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* s = new char[n + 1];
			strcpy(s, _str);
			delete[] _str;
			_str = s;
			_capacity = n;
		}
	}
	void string::clear()
	{
		_str[0] = '\0';
		_size = 0;
	}

	void string::push_back(const char& ch)
	{
		if (_size == _capacity)
		{
			reserve(_capacity == 0 ? 4 : 2 * _capacity);
		}
		_str[_size++] = ch;
		_str[_size] = '\0';
	}

	void string::insert(size_t pos, const char& ch)
	{
		assert(pos <= _size);

		if (_size == _capacity)
		{
			reserve(_capacity == 0 ? 4 : 2 * _capacity);
		}
		//这样会造成死循环
	/*	int i = _size;
		for (; i >= pos; i--)
		{
			_str[i + 1] = _str[i];
		}
		_str[pos] = ch;
		++_size;*/

		size_t i = _size + 1;
		for (; i > pos; i--)
		{
			_str[i] = _str[i - 1];
		}
		_str[pos] = ch;
		++_size;
	}
	void string::insert(size_t pos, const char* s)
	{
		assert(pos <= _size);
		size_t len = strlen(s);
		//不能这样扩容，因为当插入的字符串很长时，扩容到当前容量的二倍也不够
		/*if (_size == _capacity)
		{
			reserve(_capacity == 0 ? 4 : 2 * _capacity);
		}*/
		if (_capacity < len + _size)
		{
			reserve(2 * _capacity < len + _size ? len + _size : 2 * _capacity);
		}

		size_t i = _size + len;
		for (; i >= pos + len; i--)
		{
			_str[i] = _str[i - len];
		}

		for (i = 0; i < len; i++)
		{
			_str[pos + i] = s[i];
		}
		_size += len;
	}

	void string::append(const char* s)
	{
		insert(_size, s);
	}

	string& string::operator+=(char ch)
	{
		if (_size == _capacity)
		{
			reserve(2 * _capacity);
		}
		_str[_size++] = ch;
		_str[_size] = '\0';

		return *this;
	}
	string& string::operator+=(const char* s)
	{
		append(s);
		return *this;
	}

	string& string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);

		if (len == npos)
		{
			_str[pos] = '\0';
			_size = pos;
		}
		else
		{
			size_t end = pos + len - 1;
			size_t i = pos + len;
			while (i <= _size)
			{
				_str[pos] = _str[i];

				++pos;
				++i;
			}
			_size -= len;
		}

		return *this;
	}

	bool operator>(const string& str1, const string& str2)
	{
		return strcmp(str1.c_str(), str2.c_str()) > 0;
	}
	bool operator>=(const string& str1, const string& str2)
	{
		return str1 > str2 || str1 == str2;
	}
	bool operator<(const string& str1, const string& str2)
	{
		return !(str1 >= str2);
	}
	bool operator<=(const string& str1, const string& str2)
	{
		return !(str1 > str2);
	}
	bool operator==(const string& str1, const string& str2)
	{
		return strcmp(str1.c_str(), str2.c_str()) == 0;
	}
	bool operator!=(const string& str1, const string& str2)
	{
		return !(str1 == str2);
	}

	std::istream& operator>>(std::istream& input, string& str)
	{
		//需要频繁扩容
		/*str.clear();

		char ch = '0';
		ch = input.get();
		
		while (ch != ' ' && ch != '\n')
		{
			str += ch;
			ch = input.get();
		}
		return input;*/

		str.clear();
		const int N = 5;
		char buffer[N] = { 0 };

		char ch = 0;
		ch = input.get();
		int i = 0;
		while (ch != ' ' && ch != '\n')
		{
			buffer[i++] = ch;
			if (i == N-2)
			{
				buffer[N-1] = '\0';
				i = 0;
				str += buffer;
			}

			ch = input.get();
		}
		if (i != 0)
		{
			buffer[i] = '\0';
			str += buffer;
		}

		return input;
	}

	std::ostream& operator<<(std::ostream& output, const string& str)
	{
		for (auto ch : str)
		{
			output << ch;
		}
		return output;
	}

	size_t string::find(const char* s, size_t pos)
	{
		assert(pos < _size);

		char* tmp = strstr(_str + pos, s);
		if (tmp)
		{
			return tmp - _str;
		}
		else
		{
			return npos;
		}
	}

	size_t string::find(char ch, size_t pos)
	{
		assert(pos < _size);

		size_t i = pos;
		for (; i < _size; i++)
		{
			if (_str[i] == ch)
			{
				return i;
			}
		}
		return string::npos;
	}

	string string::substr(size_t pos, size_t len)
	{
		assert(pos < _size);

		if (len > _size - pos)
		{
			len = _size - pos;
		}

		char buffer[256] = { 0 };
		strncpy(buffer, _str + pos, len);
		string ans(buffer);
		return ans;

		/*string ans;
		size_t i = pos;
		while (len--)
		{
			ans += _str[i++];
		}
		ans += '\0';

		return ans;*/
	}
	
	void string::swap(string& s)
	{
		std::swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);
	}
}